home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / x1.zip / XTEST.C < prev    next >
Text File  |  1993-05-19  |  25KB  |  1,089 lines

  1.  
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <dos.h>
  5. #include <math.h>
  6. #include <mem.h>
  7. #include <alloc.h>
  8. #include <io.h>
  9. #include <fcntl.h>
  10. #include <string.h>
  11. #include "vga240.h"
  12.  
  13. #define KEYBD  0x9    /* INTERRUPT 9 */
  14.  
  15. #define RIGHT_ARROW_PRESSED   77
  16. #define RIGHT_ARROW_RELEASED  205
  17. #define UP_ARROW_PRESSED      72
  18. #define UP_ARROW_RELEASED     200
  19. #define LEFT_ARROW_PRESSED    75
  20. #define LEFT_ARROW_RELEASED   203
  21. #define DOWN_ARROW_PRESSED    80
  22. #define DOWN_ARROW_RELEASED   208
  23. #define CONTROL_PRESSED          29
  24. #define CONTROL_RELEASED      157
  25. #define ESCAPE              1
  26. #define HOME_PRESSED          71
  27. #define HOME_RELEASED          199
  28. #define PGUP_PRESSED          73
  29. #define PGUP_RELEASED          201
  30. #define PGDN_PRESSED          81
  31. #define PGDN_RELEASED          209
  32. #define END_PRESSED          79
  33. #define END_RELEASED          207
  34. #define PLUS_PRESSED          78
  35. #define PLUS_RELEASED          206
  36. #define MINUS_PRESSED          74
  37. #define MINUS_RELEASED          202
  38.  
  39. volatile unsigned char scanCode;
  40.  
  41. struct{
  42.     int rightArrow;
  43.     int leftArrow;
  44.     int upArrow;
  45.     int downArrow;
  46.     int home;
  47.     int pgup;
  48.     int pgdn;
  49.     int end;
  50.     int control;
  51.     int alt;
  52.     int plus;
  53.     int minus;
  54.     int escape;
  55. }keyBoard;
  56.  
  57. char numLockKeyStatus;
  58.  
  59. void interrupt (*oldvec)();
  60. void interrupt myInt();
  61.  
  62. void DrawLine(int,int,int,int,int);
  63. void SetPixel(int,int,int);
  64. void DspString(int,int,char *,int);
  65. void SetVmode(int);
  66. void keyCheck(void);
  67.  
  68.     long    LastX1;
  69.     long    LastY1;
  70.     int    LastPosn;
  71.     int    PageNum;
  72.     FILE    *dfp;
  73.  
  74.  
  75. /* Map of walls. This array is used to build the xRay and yRay grids */
  76. /* when checking the x and y vectors */
  77.  
  78. unsigned char    Grid[] = {2,6,4,3,6,5,8,9,2,3,
  79.               3,0,0,0,4,0,0,0,0,4,
  80.               4,0,0,0,6,0,0,0,0,5,
  81.               3,0,0,0,5,0,3,4,3,6,
  82.               2,0,0,0,0,0,0,0,0,5,
  83.               9,6,5,8,9,0,4,3,6,8,
  84.               8,0,0,0,0,0,0,0,0,9,
  85.               5,0,0,0,6,0,0,0,0,2,
  86.               6,0,0,0,5,0,0,0,0,3,
  87.               3,4,3,2,9,8,5,6,3,4
  88.             };
  89.  
  90.  
  91.  
  92. #define GRID_WIDTH  10
  93. #define GRID_HEIGHT 10
  94. #define GRID_MAX    GRID_WIDTH * GRID_HEIGHT
  95. #define GRID_XSTEP  64                /* X distance between walls */
  96. #define GRID_YSTEP  64                /* Y distance between walls */
  97. #define GRID_XMAX   GRID_XSTEP * GRID_WIDTH
  98. #define GRID_YMAX   GRID_YSTEP * GRID_HEIGHT
  99.  
  100. #define BITMAP_HEIGHT    64
  101. #define BITMAP_WIDTH    64
  102.  
  103. #define ANGLE_0        0            /* Angles used for lookup */
  104. #define ANGLE_30    171            /*  tables...          */
  105. #define ANGLE_45    256
  106. #define ANGLE_60    341
  107. #define ANGLE_90    512
  108. #define ANGLE_180    1024
  109. #define ANGLE_270    1536
  110. #define ANGLE_360    2048
  111.  
  112. #define DEC_FACTOR    15            /* Shift factor for fixed pt */
  113. #define DEC_MULT    32768            /* 1 << DEC_FACTOR         */
  114.  
  115. #define ULPTR        long far *
  116.  
  117. unsigned    char    xGrid[(GRID_WIDTH+2) * (GRID_HEIGHT+2)];
  118. unsigned    char    yGrid[(GRID_WIDTH+2) * (GRID_HEIGHT+2)];
  119.  
  120.     long far    *cTable;            /* Cosine table     */
  121.     long far    *sTable;            /* Sine table     */
  122.     long far    *tTable;            /* Tangent table */
  123.  
  124.     long far    *nxTable;            /* Next X offset per angle */
  125.     long far    *nyTable;            /* Next Y offset per angle */
  126.  
  127.     long        DstTable[3072];        /* Distance to height table */
  128.  
  129.     int        fv[360];            /* Filter view angles       */
  130.  
  131.  
  132. /****************************************************************************
  133. ** Allocate tables                               **
  134. ****************************************************************************/
  135. void GetTables(void)
  136. {
  137.  
  138. cTable = (ULPTR)farmalloc(sizeof(long) * ANGLE_360);
  139. sTable = (ULPTR)farmalloc(sizeof(long) * ANGLE_360);
  140. tTable = (ULPTR)farmalloc(sizeof(long) * ANGLE_360);
  141. nxTable = (ULPTR)farmalloc(sizeof(long) * ANGLE_360);
  142. nyTable = (ULPTR)farmalloc(sizeof(long) * ANGLE_360);
  143.  
  144. }
  145.  
  146. /****************************************************************************
  147. ** Check int 9 scancode and set appropriate bit in kbd structure       **
  148. ****************************************************************************/
  149. void keyCheck(void)
  150. {
  151.   if(scanCode==RIGHT_ARROW_PRESSED)keyBoard.rightArrow=1;
  152.   if(scanCode==RIGHT_ARROW_RELEASED)keyBoard.rightArrow=0;
  153.   if(scanCode==UP_ARROW_PRESSED)keyBoard.upArrow=1;
  154.   if(scanCode==UP_ARROW_RELEASED)keyBoard.upArrow=0;
  155.   if(scanCode==LEFT_ARROW_PRESSED)keyBoard.leftArrow=1;
  156.   if(scanCode==LEFT_ARROW_RELEASED)keyBoard.leftArrow=0;
  157.   if(scanCode==DOWN_ARROW_PRESSED)keyBoard.downArrow=1;
  158.   if(scanCode==DOWN_ARROW_RELEASED)keyBoard.downArrow=0;
  159.   if(scanCode==CONTROL_PRESSED)keyBoard.control=1;
  160.   if(scanCode==CONTROL_RELEASED)keyBoard.control=0;
  161.   if(scanCode==HOME_PRESSED)keyBoard.home=1;
  162.   if(scanCode==HOME_RELEASED)keyBoard.home=0;
  163.   if(scanCode==END_PRESSED)keyBoard.end=1;
  164.   if(scanCode==END_RELEASED)keyBoard.end=0;
  165.   if(scanCode==PGUP_PRESSED)keyBoard.pgup=1;
  166.   if(scanCode==PGUP_RELEASED)keyBoard.pgup=0;
  167.   if(scanCode==PGDN_PRESSED)keyBoard.pgdn=1;
  168.   if(scanCode==PGDN_RELEASED)keyBoard.pgdn=0;
  169.   if(scanCode==ESCAPE)keyBoard.escape=1;
  170.   if(scanCode==PLUS_PRESSED)keyBoard.plus = 1;
  171.   if(scanCode==PLUS_RELEASED)keyBoard.plus = 0;
  172.   if(scanCode==MINUS_PRESSED)keyBoard.minus = 1;
  173.   if(scanCode==MINUS_RELEASED)keyBoard.minus = 0;
  174.  
  175.  
  176.  
  177. }
  178.  
  179.  
  180. /****************************************************************************
  181. ** Called during an int 9 (keyboard interrupt)                   **
  182. ****************************************************************************/
  183. void interrupt myInt()
  184. {
  185.   register char x;
  186.   scanCode = inp(0x60); // read keyboard data port
  187.   x = inp(0x61);
  188.   outp(0x61, (x | 0x80));
  189.   outp(0x61, x);
  190.   outp(0x20, 0x20);
  191.   keyCheck();
  192. }
  193.  
  194. /****************************************************************************
  195. **                                       **
  196. ****************************************************************************/
  197. void keyBoardReset(void)
  198. {
  199.   pokeb(0x0040,0x0017,numLockKeyStatus);   // return old keyboard status
  200. }
  201.  
  202. /****************************************************************************
  203. ** Clear kbd structure and hold onto old numlock status               **
  204. **                   (Not really needed for this app)       **
  205. ****************************************************************************/
  206. void keyBoardInit(void)
  207. {
  208.   int value=0;
  209.   keyBoard.rightArrow=0;
  210.   keyBoard.upArrow=0;
  211.   keyBoard.leftArrow=0;
  212.   keyBoard.downArrow=0;
  213.   keyBoard.control=0;
  214.   keyBoard.escape=0;
  215.   value=peekb(0x0040,0x0017);
  216.   if(value & 32){
  217.     numLockKeyStatus=value;
  218.     pokeb(0x0040,0x0017,0);   // turn off num lock key temporarly
  219.   }
  220.   else
  221.     numLockKeyStatus=0;
  222. }
  223.  
  224. /****************************************************************************
  225. ** Check for a hit within the Y wall grid                   **
  226. ****************************************************************************/
  227. int CheckHitY(long x,long y)
  228. {
  229.     long    x1,y1;
  230.  
  231. if (x < 0 || y < 0 || x > GRID_XMAX || y > GRID_YMAX)
  232.     return(0);
  233.  
  234. x1 = x >> 6;    /* Divide by 64 */
  235. y1 = y >> 6;    /* Divide by 64 */
  236.  
  237. y1 *= GRID_WIDTH;
  238. return(yGrid[y1+x1]);
  239. }
  240.  
  241. /****************************************************************************
  242. ** Check for a hit within the X wall grid                   **
  243. ****************************************************************************/
  244. int CheckHitX(long x,long y)
  245. {
  246.     long    x1,y1;
  247.  
  248. if (x < 0 || y < 0 || x > GRID_XMAX || y > GRID_YMAX)
  249.     return(0);
  250.  
  251. x1 = x >> 6;    /* Divide by 64 */
  252. y1 = y >> 6;    /* Divide by 64 */
  253.  
  254. y1 *= GRID_WIDTH;
  255. return(xGrid[y1+x1]);
  256. }
  257.  
  258.  
  259. /****************************************************************************
  260. ** Check for a hit within the master grid (used during movement)       **
  261. ****************************************************************************/
  262. int CheckHit(long x,long y)
  263. {
  264.     int        gPosn;
  265.  
  266. if (x < 0 || y < 0 || x > GRID_XMAX || y > GRID_YMAX)
  267.     return(0);
  268.  
  269. gPosn = ((y >> 6) * GRID_WIDTH) + (x >> 6);
  270.  
  271. if (gPosn < 0 || gPosn > GRID_MAX)
  272.     return(0);
  273.  
  274. LastPosn = gPosn;
  275.  
  276. return(Grid[gPosn]);
  277. }
  278.  
  279.  
  280. /****************************************************************************
  281. ** Return the square root of a long value                   **
  282. ****************************************************************************/
  283. long long_sqrt(long v)
  284. {
  285.     int        i;
  286.     unsigned    long result,tmp;
  287.     unsigned    long low,high;
  288.  
  289. if (v <= 1L) return((unsigned)v);
  290.  
  291. low = v;
  292. high = 0L;
  293. result = 0;
  294.  
  295. for (i = 0; i < 16; i++)
  296.     {
  297.     result += result;
  298.     high = (high << 2) | ((low >>30) & 0x3);
  299.     low <<= 2;
  300.  
  301.     tmp = result + result + 1;
  302.     if (high >= tmp)
  303.     {
  304.     result++;
  305.     high -= tmp;
  306.     }
  307.     }
  308.  
  309. return(result);
  310. }
  311.  
  312. /****************************************************************************
  313. ** Cast a ray along the X walls to see if a hit occurs               **
  314. **                                       **
  315. ** General flow:                               **
  316. **  1) Determine the border of the current grid square to start from. This **
  317. **     will be based on the angle facing.                   **
  318. **                                       **
  319. **  2) Calculate the amount to add to the Y coordinate for every step made **
  320. **     through the X walls. The X amount will be constant once we start       **
  321. **     from the border in step 1.                       **
  322. **                                       **
  323. **  3) Check for a color value in the X grid. If non-zero then a wall is   **
  324. **     present so set our global values for X1 and Y1 and return the color.**
  325. **                                       **
  326. **  4) Add the calculated amounts to both X and Y (X is constant at 64 or  **
  327. **     -64 based on the angle) and go back to step 3 looping until a wall  **
  328. **     is hit or we go beyond the edges of the map grid.           **
  329. **                                       **
  330. **                                       **
  331. **                                       **
  332. ****************************************************************************/
  333. char xRay(long x,long y,int CurAng)
  334. {
  335.     long    x1,y1;
  336.     int        xbeg;
  337.     int        posn;
  338.     long    Adj,nx,ny;
  339.     long    tvalue;
  340.     char    ch;
  341.  
  342. if (CurAng == ANGLE_90 || CurAng == ANGLE_270)    /* Don't check vertical lines */
  343.     return(0);
  344.  
  345. xbeg = x & 0xFFC0;        /* Same as (X / 64) * 64 to get upper left X */
  346. tvalue = tTable[CurAng];
  347.  
  348. ny = nyTable[CurAng];
  349.  
  350. if (!CurAng)
  351.     {
  352.     x1 = xbeg + GRID_XSTEP;
  353.     y1 = 0;
  354.     nx = GRID_XSTEP;
  355.     ny = 0;
  356.     }
  357. else
  358.     {
  359.     if (CurAng > ANGLE_270 || CurAng < ANGLE_90)
  360.     {
  361.     x1 = xbeg + GRID_XSTEP;
  362.     Adj = x1 - x;
  363.     y1 = (long)(tvalue * Adj) >> DEC_FACTOR;
  364.     nx = GRID_XSTEP;
  365.     }
  366.     }
  367.  
  368.  
  369. if (CurAng == ANGLE_180)
  370.     {
  371.     x1 = xbeg;
  372.     y1 = 0;
  373.     nx = -GRID_XSTEP;
  374.     ny = 0;
  375.     }
  376. else
  377.     {
  378.     if (CurAng > ANGLE_90 && CurAng < ANGLE_270)
  379.     {
  380.     x1 = xbeg;
  381.     Adj = x1 - x;
  382.     y1 = (long)(tvalue * Adj) >> DEC_FACTOR;
  383.     nx = -GRID_XSTEP;
  384.     }
  385.     }
  386.  
  387. if (CurAng > ANGLE_180)
  388.     ny = -ny;
  389.  
  390. y1 += y;
  391.  
  392. while (1)
  393.     {
  394.     if (x1 > GRID_XMAX || y1 > GRID_YMAX ||
  395.     x1 < 0 || y1 < 0)
  396.     break;
  397.  
  398.     posn = ((y1 >> 6) * GRID_WIDTH) + (x1 >> 6);
  399.     ch = xGrid[posn];
  400.     if (ch)
  401.     {
  402.     LastX1 = x1;
  403.     LastY1 = y1;
  404.     return(ch);
  405.     }
  406.  
  407.     x1 += nx;
  408.     y1 += ny;
  409.     }
  410.  
  411. return(0);
  412. }
  413.  
  414.  
  415. /****************************************************************************
  416. ** Cast a ray along the Y walls to see if a hit occurs               **
  417. **                                       **
  418. ** General flow:                               **
  419. **  1) Determine the border of the current grid square to start from. This **
  420. **     will be based on the angle facing.                   **
  421. **                                       **
  422. **  2) Calculate the amount to add to the X coordinate for every step made **
  423. **     through the Y walls. The Y amount will be constant once we start       **
  424. **     from the border in step 1.                       **
  425. **                                       **
  426. **  3) Check for a color value in the Y grid. If non-zero then a wall is   **
  427. **     present so set our global values for X1 and Y1 and return the color.**
  428. **                                       **
  429. **  4) Add the calculated amounts to both X and Y (Y is constant at 64 or  **
  430. **     -64 based on the angle) and go back to step 3 looping until a wall  **
  431. **     is hit or we go beyond the edges of the map grid.           **
  432. **                                       **
  433. **                                       **
  434. ****************************************************************************/
  435. char yRay(long x,long y,int CurAng)
  436. {
  437.     long    x1,y1;
  438.     int        ybeg;
  439.     int        posn;
  440.     long    Opp,nx,ny;
  441.     long    tvalue;
  442.     char    ch;
  443.  
  444. if (CurAng == 0 || CurAng == ANGLE_180)        /* No need to check horiz lines */
  445.     return(0);
  446.  
  447. ybeg = y & 0xFFC0;        /* Same as (Y / 64) * 64 to get upper left Y */
  448.  
  449. tvalue = tTable[CurAng];    /* Tangent value for the current angle  */
  450.  
  451. nx = nxTable[CurAng];        /* X amount for the current angle        */
  452.  
  453. if (CurAng == ANGLE_90)
  454.     {
  455.     x1 = 0;
  456.     y1 = ybeg + GRID_YSTEP;
  457.     ny = GRID_YSTEP;
  458.     nx = 0;
  459.     }
  460. else
  461.     {
  462.     if (CurAng > 0 && CurAng < ANGLE_180)
  463.     {
  464.     y1 = ybeg + GRID_YSTEP;
  465.     Opp = y1 - y;
  466.     Opp <<= DEC_FACTOR;
  467.     x1 = Opp / tvalue;
  468.     ny = GRID_YSTEP;
  469.     }
  470.     }
  471.  
  472. if (CurAng == ANGLE_270)
  473.     {
  474.     x1 = 0;
  475.     y1 = ybeg;
  476.     ny = -GRID_YSTEP;
  477.     nx = 0;
  478.     }
  479. else
  480.     {
  481.     if (CurAng > ANGLE_180)
  482.     {
  483.     y1 = ybeg;
  484.     Opp = y1 - y;
  485.     Opp <<= DEC_FACTOR;
  486.     x1 = Opp / tvalue;
  487.     ny = -GRID_YSTEP;
  488.     }
  489.     }
  490.  
  491. if (CurAng > ANGLE_90 && CurAng < ANGLE_270)
  492.     nx = -nx;
  493.  
  494. x1 += x;
  495.  
  496. while (1)
  497.     {
  498.     if (x1 > GRID_XMAX || y1 > GRID_YMAX ||
  499.     x1 < 0 || y1 < 0)
  500.     break;
  501.  
  502.     posn = ((y1 >> 6) * GRID_WIDTH) + (x1 >> 6);
  503.     ch = yGrid[posn];
  504.     if (ch)
  505.     {
  506.     LastX1 = x1;
  507.     LastY1 = y1;
  508.     return(ch);
  509.     }
  510.  
  511.     x1 += nx;
  512.     y1 += ny;
  513.     }
  514.  
  515. return(0);
  516. }
  517.  
  518. /****************************************************************************
  519. ** Display an entire screen worth of walls.                   **
  520. ** General flow:                               **
  521. **  1) Fill in sky and floor colors.                       **
  522. **  2) Begin looping from left side of screen to right side (320 width)       **
  523. **  3) Cast a ray along the X walls to see if a hit, returns wall color.   **
  524. **  4) If a hit calc the xDistance using c2 = a2 + b2               **
  525. **  5) Cast a ray along the Y walls to see if a hit, returns wall color.   **
  526. **  6) If a hit calc the yDistance using c2 = a2 + b2               **
  527. **  7) If xDistance less or equal then yDistance then use xColor and xDist **
  528. **     else use yColor and yDistance.                       **
  529. **  8) Use the Cosine of the starting angle minus the current angle to       **
  530. **     adjust the distance for a flat view.                   **
  531. **  9) Get the height from the distance table.                   **
  532. **  10) Draw a vertical line using the height and color.           **
  533. **  11) Go back to set 3 until full screen is painted.               **
  534. **                                       **
  535. ** NOTE: This routine needs ALOT of optimizing yet, just trying to get       **
  536. **     the basics down for now.                       **
  537. **                                       **
  538. ****************************************************************************/
  539. void DrawView(long x,long y,long angle)
  540. {
  541.     int        i,CurAng,CalcAng;
  542.     char    color,xcolor,ycolor;
  543.     long    xDst,yDst,dst,deltax,deltay;
  544.     long    ht,ty,ty1,vx,vy;
  545.  
  546. for (i = 0; i < 120; i++)        /* Fill in sky on upper half    */
  547.     hline(0,319,i,1);
  548.  
  549. for (i = 120; i < 240; i++)        /* Fill in floor on lower half    */
  550.     hline(0,319,i,21);
  551.  
  552. for (i = 0; i < 320; i++)
  553.     {
  554.  
  555.     CurAng = angle + fv[i+20];
  556.     if (CurAng < 0)
  557.     CurAng = ANGLE_360 + CurAng;
  558.     if (CurAng >= ANGLE_360)
  559.     CurAng = CurAng - ANGLE_360;
  560.  
  561.     CalcAng = abs(angle - CurAng);
  562.     if (CalcAng < 0)
  563.     CalcAng = ANGLE_360 + CalcAng;
  564.     if (CalcAng >= ANGLE_360)
  565.     CalcAng = CalcAng - ANGLE_360;
  566.  
  567.  
  568.     xDst = yDst = 1000000L;        /* Set to wild distance for later compare */
  569.  
  570.     xcolor = xRay(x,y,CurAng);
  571.     if (xcolor)                /* A hit on an X wall */
  572.     {
  573.     deltax = labs(LastX1 - x);
  574.     deltay = labs(LastY1 - y);
  575.     xDst = long_sqrt((deltax * deltax) + (deltay * deltay));
  576.     }
  577.  
  578.     ycolor = yRay(x,y,CurAng);
  579.     if (ycolor)                /* A hit on a Y wall */
  580.     {
  581.     deltax = labs(LastX1 - x);
  582.     deltay = labs(LastY1 - y);
  583.     yDst = long_sqrt((deltax * deltax) + (deltay * deltay));
  584.     }
  585.  
  586.     if (xcolor || ycolor)
  587.     {
  588.  
  589.     if (xDst <= yDst)
  590.         {
  591.         color = xcolor;
  592.         dst = xDst;
  593.         }
  594.     else
  595.         {
  596.         color = ycolor;
  597.         dst = yDst;
  598.         }
  599.  
  600.     vx = cTable[CalcAng];
  601.     if (vx)
  602.         {
  603.         vy = dst * vx;
  604.         dst = vy >> DEC_FACTOR;
  605.         }
  606.  
  607.     if (dst > 3071)
  608.         dst = 3071;
  609.  
  610.     ht = DstTable[dst];
  611.  
  612.     ty = 120 - (ht/2);
  613.     ty1 = ty + ht;
  614.  
  615.     if (ty < 0) ty = 0;
  616.     if (ty1 > 239) ty1 = 239;
  617.  
  618.  
  619.     vline(i,(int)ty,(int)ty1,color);
  620.     }
  621.  
  622.     }
  623.  
  624. flippage();
  625. PageNum ^= 1;
  626. usepage(PageNum);
  627. }
  628.  
  629. /****************************************************************************
  630. ** Another approach to displaying a screen worth of walls.           **
  631. ** Use this method by specifying -O on the command line when starting       **
  632. ****************************************************************************/
  633. void OldDrawView(long x,long y,long angle)
  634. {
  635.     int        i,color,j,xcolor,ycolor,LastColor;
  636. unsigned    int        ht,ty,ty1,wt;
  637.     int        voff,vnext;
  638.     long    vx,vy;
  639. unsigned    long    deltax,deltay,dst;
  640.     int        aBias;
  641.     int        CurAng,RealAngle,CalcAng;
  642.     long    Opp,Hyp;
  643.     long    yDst,xDst,LastDst;
  644.     long    gx,gy,nextx,nexty,xoff,yoff,xbeg,ybeg;
  645.  
  646.  
  647. for (i = 0; i < 120; i++)        /* Fill in sky on upper half    */
  648.     hline(0,319,i,1);
  649.  
  650. for (i = 120; i < 240; i++)        /* Fill in floor on lower half    */
  651.     hline(0,319,i,21);
  652.  
  653. ybeg = y & 0xFFC0;            /* Get upper left corner of current */
  654. xbeg = x & 0xFFC0;            /* grid square we are in        */
  655.  
  656.  
  657. for (i = 0; i < 320; i++)        /* Draw screen width        */
  658.     {
  659.  
  660.     CurAng = angle + fv[i+20];        /* Get the next angle to use    */
  661.     if (CurAng < 0)
  662.     CurAng = ANGLE_360 + CurAng;
  663.     if (CurAng >= ANGLE_360)
  664.     CurAng = CurAng - ANGLE_360;
  665.  
  666.     CalcAng = abs(angle - CurAng);    /* Get the angle to calc distance */
  667.     if (CalcAng < 0)
  668.     CalcAng = ANGLE_360 + CalcAng;
  669.     if (CalcAng >= ANGLE_360)
  670.     CalcAng = CalcAng - ANGLE_360;
  671.  
  672.  
  673. /* Get setup to cast a ray on the Y walls */
  674.  
  675.     if (CurAng > ANGLE_180)
  676.     {
  677.     Opp = ybeg - y;
  678.     gy = ybeg;
  679.     nexty = -64;
  680.     }
  681.     else
  682.     {
  683.     Opp = (ybeg + 64L) - y;
  684.     gy = ybeg + 64;
  685.     nexty = 64;
  686.     }
  687.  
  688.     Opp <<= DEC_FACTOR;
  689.     vy = tTable[CurAng];
  690.     if (!vy)
  691.     vy = tTable[CurAng+1];        /* Fudge.....???? */
  692.  
  693.     if (!vy)
  694.     {
  695.     nextx = nxTable[CurAng+1];
  696.     gx = x - xbeg;
  697.     }
  698.     else
  699.     {
  700.     nextx = nxTable[CurAng];
  701.     gx = Opp / vy;
  702.     if (Opp - (gx * gy) >= (vy/2))
  703.         gx++;
  704.     }
  705.  
  706.     if (CurAng > ANGLE_90 && CurAng < ANGLE_270)
  707.     nextx = -nextx;
  708.  
  709.     if (!CurAng || CurAng == ANGLE_180)
  710.     nexty = 0;
  711.  
  712.  
  713.     vx = gx + x;        /* Initial X posn to check */
  714.     vy = gy;            /* Initial Y posn to check */
  715.     ycolor = 0;
  716.     yDst = 0;
  717.  
  718.     while (nexty)
  719.     {
  720.     if (vx < 0 || vy < 0 || vx > GRID_XMAX || vy > GRID_YMAX)
  721.         break;
  722.  
  723.     ycolor = CheckHitY(vx,vy);
  724.     if (ycolor)        /* Got a hit so exit loop to calc distance */
  725.         break;
  726.  
  727.     vx += nextx;
  728.     vy += nexty;
  729.  
  730.     }
  731.  
  732.     if (ycolor)
  733.     {
  734.     deltax = labs(vx - x);
  735.     deltay = labs(vy - y);
  736.  
  737.     dst = (deltax * deltax) + (deltay * deltay);
  738.  
  739.     yDst = long_sqrt(dst);
  740.  
  741.     if (dst - (yDst * yDst) > yDst)
  742.         yDst++;
  743.     }
  744.  
  745.     if (CurAng > ANGLE_90 && CurAng < ANGLE_270)
  746.     {
  747.     vx = xbeg - x;
  748.     nextx = -64;
  749.     gx = xbeg;
  750.     }
  751.     else
  752.     {
  753.     vx = (xbeg + 64) - x;
  754.     nextx = 64;
  755.     gx = xbeg + 64;
  756.     }
  757.  
  758.     gy = (vx * tTable[CurAng]) >> DEC_FACTOR;
  759.     nexty = nyTable[CurAng];
  760.  
  761.     vx = gx;
  762.     vy = gy + y;
  763.  
  764.     if (CurAng == ANGLE_90 || CurAng == ANGLE_270)
  765.     nextx = 0L;
  766.  
  767.     if (CurAng > ANGLE_180)
  768.     nexty = -nexty;
  769.  
  770.     xcolor = 0;
  771.     xDst = 0;
  772.  
  773.     while (nextx)
  774.     {
  775.  
  776.     if (vx < 0 || vy < 0 || vx > GRID_XMAX || vy > GRID_YMAX)
  777.         break;
  778.  
  779.     xcolor = CheckHitX(vx,vy);
  780.     if (xcolor)
  781.         break;
  782.  
  783.     vx += nextx;
  784.     vy += nexty;
  785.  
  786.     }
  787.  
  788.     if (xcolor)
  789.     {
  790.     deltax = labs(vx - x);
  791.     deltay = labs(vy - y);
  792.  
  793.     dst = (deltax * deltax) + (deltay * deltay);
  794.  
  795.     xDst = long_sqrt(dst);
  796.  
  797.     if (dst - (xDst * xDst) > xDst)
  798.         xDst++;
  799.  
  800.     }
  801.  
  802.  
  803.  
  804.     if (xcolor || ycolor)
  805.     {
  806.     if (yDst == 0L || xDst <= yDst)
  807.         {
  808.         dst = xDst;
  809.         color = xcolor;
  810.  
  811.         if (xDst == 0L)
  812.         {
  813.         dst = yDst;
  814.         color = ycolor;
  815.         }
  816.         }
  817.     else
  818.         {
  819.         dst = yDst;
  820.         color = ycolor;
  821.         }
  822.  
  823.     vx = cTable[CalcAng];
  824.     if (vx)
  825.         {
  826.         vy = (unsigned long)((unsigned long)dst * (unsigned long)vx);
  827.         dst = vy >> DEC_FACTOR;
  828.         }
  829.  
  830.     if (dst > 3071)
  831.         dst = 3071;
  832.  
  833.     ht = DstTable[dst];
  834.     j = ht / 2;
  835.  
  836.     ty = 120 - j;
  837.     ty1 = ty + ht;
  838.  
  839.     if (ty > 120) ty = 0;
  840.  
  841.     if (ty1 > 239) ty1 = 239;
  842.     vline(i,(int)ty,(int)ty1,color);
  843.     }
  844.  
  845.     }
  846.  
  847. flippage();
  848. PageNum ^= 1;
  849. usepage(PageNum);
  850. }
  851.  
  852.  
  853. /****************************************************************************
  854. ** Wolfenstein style engine.                           **
  855. ** General flow:                               **
  856. **  1) Allocate and intialize trig tables and X and Y offset tables.       **
  857. **  2) Build X and Y wall grids from the master grid.               **
  858. **  3) Setup keyboard intercept and switch to VGA 240 line mode (mode X)   **
  859. **  4) Initialize player X,Y and view angle.                   **
  860. **  5) Draw the initial screen of walls.                   **
  861. **  6) Wait for keyboard action. Escape key exits.               **
  862. **  7) Move forward or back or turn viewing angle based on key.           **
  863. **  8) Draw new screen full of walls and go to step 6.               **
  864. **                                       **
  865. ****************************************************************************/
  866. void main(int argc,char *argv[])
  867. {
  868.     int        done;
  869.     int        dflag,vflag;
  870.     long   x,y,x1,y1,angle,opang;
  871.     unsigned int key;
  872.     float   ang,ca;
  873.  
  874.  
  875.  
  876. done = open("f.dat",O_RDWR|O_BINARY);
  877. if (done < 1)
  878.     {
  879.     puts("Unable to open f.dat");
  880.     exit(1);
  881.     }
  882.  
  883. read(done,fv,720);
  884. close(done);
  885.  
  886. vflag = 0;
  887. if (argc > 1)
  888.     {
  889.     if (!(stricmp(argv[1],"-O")))
  890.     {
  891.     vflag = 1;
  892.     }
  893.     }
  894.  
  895. GetTables();
  896.  
  897. y1 = 12000L;
  898.  
  899. DstTable[0] = y1;
  900. for (done = 1; done < 3072; done += 1)
  901.     {
  902.     x1 = y1 / done;
  903.  
  904.     if (y1 - (x1 * done) > (done / 2))
  905.     x1++;
  906.  
  907.     DstTable[done] = x1;
  908.     }
  909.  
  910. ang = 0;
  911. ca = 6.283185307 / ANGLE_360;
  912.  
  913. for (x = 0; x < ANGLE_360; x++)
  914.     {
  915.     tTable[x] = (long)(tan(ang) * DEC_MULT);
  916.     cTable[x] = (long)(cos(ang) * DEC_MULT);
  917.     sTable[x] = (long)(sin(ang) * DEC_MULT);
  918.  
  919.     nxTable[x] = 64L;
  920.     if (tTable[x])
  921.     nxTable[x] = labs((64L << DEC_FACTOR) / tTable[x]);
  922.  
  923.     y = 64L * tTable[x];
  924.     nyTable[x] = labs(y >> DEC_FACTOR);
  925.  
  926.     ang += ca;
  927.     }
  928.  
  929. y1 = (GRID_WIDTH+1) * (GRID_HEIGHT+1);
  930. memset(xGrid,0,y1);
  931. memset(yGrid,0,y1);
  932.  
  933. for (y = 0; y < GRID_HEIGHT; y++)
  934.     {
  935.     for (x = 0; x < GRID_WIDTH; x++)
  936.     {
  937.     y1 = (y * GRID_WIDTH) + x;
  938.     done = Grid[(y * GRID_WIDTH) + x];
  939.     if (done)
  940.         {
  941.         xGrid[y1] = done;
  942.         xGrid[y1+1] = done;
  943.         yGrid[y1] = done;
  944.         yGrid[y1+GRID_WIDTH] = done;
  945.         }
  946.     }
  947.     }
  948.  
  949. keyBoardInit();
  950. oldvec=getvect(KEYBD);
  951. setvect(KEYBD,myInt);
  952.  
  953. graphinit(0,0);
  954. PageNum = 1;
  955. usepage(PageNum);
  956.  
  957. x = 96;
  958. y = 96;
  959. angle = 0;
  960. done = 0;
  961.  
  962. if (!vflag)
  963.     DrawView(x,y,angle);
  964. else
  965.     OldDrawView(x,y,angle);
  966.  
  967. dflag = 0;
  968.  
  969. while (!done)
  970.     {
  971.  
  972.     if(keyBoard.escape)
  973.     break;
  974.  
  975.     if(keyBoard.rightArrow)
  976.     {
  977.     if (keyBoard.control)
  978.         angle += ANGLE_45;
  979.     else
  980.         angle += 4;
  981.  
  982.     dflag = 1;
  983.     if (angle >= ANGLE_360)
  984.         angle = angle - ANGLE_360;
  985.     }
  986.  
  987.     if(keyBoard.leftArrow)
  988.     {
  989.     if (keyBoard.control)
  990.         angle -= ANGLE_45;
  991.     else
  992.         angle -= 4;
  993.  
  994.     if (angle < 0)
  995.         angle = ANGLE_360 + angle;
  996.     dflag = 1;
  997.     }
  998.  
  999.     if(keyBoard.upArrow)
  1000.     {
  1001.     x1 = x + (cTable[angle] * 2) / DEC_MULT;
  1002.     y1 = y + (sTable[angle] * 2) / DEC_MULT;
  1003.     if (CheckHit(x1,y1))
  1004.         break;
  1005.     x = x1;
  1006.     y = y1;
  1007.     dflag = 1;
  1008.     }
  1009.  
  1010.     if (keyBoard.home)
  1011.     {
  1012.     for (dflag = 0; dflag < 64; dflag++)
  1013.         {
  1014.         x1 = x + (cTable[angle] * 2) / DEC_MULT;
  1015.         y1 = y + (sTable[angle] * 2) / DEC_MULT;
  1016.         if (CheckHit(x1,y1))
  1017.         break;
  1018.         x = x1;
  1019.         y = y1;
  1020.         }
  1021.     dflag = 1;
  1022.     }
  1023.  
  1024.     if (keyBoard.pgup)
  1025.     {
  1026.     for (dflag = 0; dflag < 10; dflag++)
  1027.         {
  1028.         x1 = x + (cTable[angle] * 2) / DEC_MULT;
  1029.         y1 = y + (sTable[angle] * 2) / DEC_MULT;
  1030.         if (CheckHit(x1,y1))
  1031.         break;
  1032.         x = x1;
  1033.         y = y1;
  1034.         }
  1035.     dflag = 1;
  1036.     }
  1037.  
  1038.     if (keyBoard.end)
  1039.     {
  1040.     opang = angle + ANGLE_180;
  1041.     if (opang >= ANGLE_360)
  1042.         opang = opang - ANGLE_360;
  1043.     for (dflag = 0; dflag < 64; dflag++)
  1044.         {
  1045.         x1 = x + (cTable[opang] * 2) / DEC_MULT;
  1046.         y1 = y + (sTable[opang] * 2) / DEC_MULT;
  1047.         if (CheckHit(x1,y1))
  1048.         break;
  1049.         x = x1;
  1050.         y = y1;
  1051.         }
  1052.     dflag = 1;
  1053.     }
  1054.  
  1055.     if (keyBoard.pgdn)
  1056.     {
  1057.     opang = angle + ANGLE_180;
  1058.     if (opang >= ANGLE_360)
  1059.         opang = opang - ANGLE_360;
  1060.     for (dflag = 0; dflag < 10; dflag++)
  1061.         {
  1062.         x1 = x + (cTable[opang] * 2) / DEC_MULT;
  1063.         y1 = y + (sTable[opang] * 2) / DEC_MULT;
  1064.         if (CheckHit(x1,y1))
  1065.         break;
  1066.         x = x1;
  1067.         y = y1;
  1068.         }
  1069.     dflag = 1;
  1070.     }
  1071.  
  1072.     if (dflag)
  1073.     {
  1074.     dflag = 0;
  1075.     if (!vflag)
  1076.         DrawView(x,y,angle);
  1077.     else
  1078.         OldDrawView(x,y,angle);
  1079.     }
  1080.  
  1081.     }
  1082.  
  1083. textmode(3);
  1084. setvect(KEYBD,oldvec);
  1085. keyBoardReset();
  1086.  
  1087. }
  1088.  
  1089.